package com.platform.boot.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.relational.core.query.Criteria;
import org.springframework.util.ObjectUtils;

import java.util.*;

/**
 * @author <a href="https://github.com/vnobo">Alex bob</a>
 */
public class CriteriaUtils {

    public static String applyPage(Pageable pageable) {
        StringBuilder sqlBuilder = applySort(pageable.getSort());
        sqlBuilder.append(" offset ").append(pageable.getOffset())
                .append(" limit ").append(pageable.getPageSize());
        return sqlBuilder.toString();
    }

    public static StringBuilder applySort(Sort sort) {
        StringBuilder sqlBuilder = new StringBuilder();
        if (sort == null || sort.isUnsorted()) {
            return sqlBuilder.append(" ORDER BY id desc ");
        }
        sqlBuilder.append(" ORDER BY ");
        StringJoiner sortSql = new StringJoiner(" , ");
        sort.iterator().forEachRemaining((o) -> {
            String sortedPropertyName = underLineToCamel(o.getProperty());
            String sortedProperty = o.isIgnoreCase() ? "LOWER(" + sortedPropertyName + ")" : sortedPropertyName;
            sortSql.add(sortedProperty + (o.isAscending() ? " ASC" : " DESC"));
        });
        return sqlBuilder.append(sortSql);
    }

    private static String underLineToCamel(String source) {
        return StrUtil.toUnderlineCase(source);
    }

    /**
     * 序列化对象条件
     *
     * @param object 需要序列化得实体
     * @return 拼接后得Criteria
     */
    public static Criteria build(Object object) {
        return build(object, List.of());
    }

    /**
     * 序列化对象条件
     *
     * @param object  需要序列化得实体
     * @param skipKes 需要跳过得序列化字段
     * @return 拼接后得Criteria
     */
    public static Criteria build(Object object, List<String> skipKes) {
        Map<String, Object> objectMap = BeanUtil.beanToMap(object, false, true);
        skipKes.forEach(objectMap::remove);
        return build(objectMap);
    }

    /**
     * 序列化对象条件
     * <p>增加String类型,数字类型number</p>
     *
     * @param objectMap 需要序列化得Map对象,key为字段,value为值
     * @return 拼接后得Criteria
     */
    public static Criteria build(Map<String, Object> objectMap) {
        if (ObjectUtils.isEmpty(objectMap)) {
            return Criteria.empty();
        }
        List<Criteria> criteriaList = new ArrayList<>();
        objectMap.forEach((key, value) -> {
            if (value instanceof String s) {
                criteriaList.add(Criteria.where(key).like(s + "%").ignoreCase(true));
            } else if (value instanceof Collection<?> c) {
                criteriaList.add(Criteria.where(key).in(c));
            } else {
                criteriaList.add(Criteria.where(key).is(value));
            }
        });
        return Criteria.from(criteriaList);
    }
}